<?php

class XMLNewsParser
{
	/**
	 * @access	private
	 * @var		array	database connection parameters
	 */
	private $_db			= array('username'	=> 'forexnews',
						'userpass'	=> 'forexnews',
						'hostname'	=> '127.0.0.1',
						'basename'	=> 'forex',
						'tablename'	=> 'forexnews');

	/**
	 * @access	private
	 * @var resource
	 */
	private	$_dbLink;

	/**
	 * @access	private
	 * @var		boolean
	 */
	private $_dbConnect		= FALSE;

	/**
	 * @access	private
	 * @var		string	XML directory path
	 */
	private $_XMLDir		= '';

	/**
	 * @access	private
	 * @var		string	XML filename
	 */
	private $_XMLFile		= '';

	/**
	 * @access	private
	 * @var		string
	 */
	private $_XMLFileExt		= 'xml';
	/**
	 * @access	private
	 * @var		array
	 */
	private	$_errors 		= array();

	/**
	 * @access	private
	 * @var		boolean
	 */
	private $_error			= FALSE;

	/**
	 * @access	private
	 * @var		object	xml object
	 */
	private $_xml;

	/**
	 * @access	private
	 * @var		string	parsed Title tag
	 */
	private $_Title;

	/**
	 * @access	private
	 * @var		string	unix TIMESTAMP
	 */
	private $_Time;

	/**
	 * @access	private
	 * @var		string	parsed Text & Data tags
	 */
	private $_Text;

	/**
	 * @access	private
	 * @var		string	parsed Table tag
	 */
	private $_Table;

	/**
	 * @access	private
	 * @var		string	prefix for Text tag
	 */
	private	$_TextPrefix		= "";

	/**
	 * @access	private
	 * @var		string	suffix for Text tag
	 */
	private $_TextSuffix		= "\n";


	/**
	 * Constructor
	 *
	 * @access	public
	 * @param	string	directory path
	 */
	public function __construct()
	{
		$arg_list = func_get_args();

		if (isset($arg_list[0])) $this->setXMLDir($arg_list[0]);

		if (!$this->dbConnect()) $this->_ErrorCollector(__METHOD__,'Could not connect to database');

	}

	/**
	 * Open database connection
	 *
	 * @access	public
	 * @ruturn	boolean	TRUE on success or FALSE on failure
	 */
	public function dbConnect()
	{
		$this->_dbLink = @mysqli_connect(	$this->_db['hostname'],
							$this->_db['username'],
							$this->_db['userpass'],
							$this->_db['basename']);

		if (!$this->_dbLink)
		{
			$this->_ErrorCollector(__METHOD__,'Could not connect: ('.mysqli_connect_errno().') '.mysqli_connect_error());
			return 0;
		}
		$this->_setDBConnect();

		@mysqli_query($this->_dbLink, "SET NAMES 'cp1251'");

		return 1;
	}

	/**
	 * Close database coonection
	 *
	 * @access	public
	 */
	public function dbDisconnect()
	{
		if ($this->_getDBConnect())
		{
			mysqli_close($this->_dbLink);
			$this->_resetDBConnect();
		}
	}

	/**
	 * Parse XML file
	 *
	 * @access	public
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	public function parse()
	{
		if ($this->getError()) {return 0;}

		if (!$this->_loadXML())
		{
			$this->_ErrorCollector(__METHOD__,'Parsing aborted');

			return 0;
		}

		foreach ($this->_xml->InfoItem->children() as $item)
		{

			switch ($item->getName())
			{
				case 'Title':	$this->_parseTitle($item);
				break;

				case 'Time':	$this->_parseTime($item);
				break;

				case 'Text':	$this->_parseText($item);
				break;

				case 'Data':	$this->_parseData($item);
				break;
				default:		break;
			}
		}

		$this->_push();

		$this->_Title ='';
		$this->_Time ='';
		$this->_Text ='';

		return 1;
	}

	/**
	 * Parse all XML files
	 *
	 * @access	public
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	public function parseAll()
	{
		if ($this->getError()) {return 0;}

		$dir = opendir($this->getXMLDir());

		while($file = readdir($dir))
		{
			if (is_file($this->getXMLDir().$file))
			{
				$fileinfo = pathinfo($this->getXMLDir().$file);

				if ($this->_XMLFileExt == strtolower($fileinfo['extension']))
				{
					$this->setXMLFile($file);
					
					if (!$this->parse())
					{
						$this->_ErrorCollector(__METHOD__,'Parsing aborted');
						return 0;
					}
				}

			}
		}
		return 1;
	}

	/**
	 * Push parsed data to database table
	 *
	 * @access	private
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	private	function _push()
	{
		if ($this->getError()) {return 0;}
			
		if (!$this->_getDBConnect())
		{
			$this->_ErrorCollector(__METHOD__,'Database not connected');
			return 0;
		}

		$this->_Title = mysqli_real_escape_string($this->_dbLink, $this->_Title);
		$this->_Time = mysqli_real_escape_string($this->_dbLink, $this->_Time);
		$this->_Text = mysqli_real_escape_string($this->_dbLink, $this->_Text);

		$query_string = "INSERT INTO ".$this->_db['tablename']." (forexnews_title, forexnews_date, forexnews_text) VALUES ( '".
		$this->_Title."', '".
		$this->_Time."', '".
		$this->_Text."' )";

		if (!mysqli_query($this->_dbLink, $query_string))
		{
			$this->_ErrorCollector(__METHOD__,'MySQLi error: '.mysqli_error($this->_dbLink));
			return 0;
		}
		return 1;
	}

	/**
	 * Parse Title tag
	 *
	 * @access	private
	 * @param	object
	 */
	private function _parseTitle($item)
	{
		$this->_Title .= $item;
	}

	/**
	 * Parse Time tag
	 *
	 * @access	private
	 * @param	object
	 */
	private function _parseTime($item)
	{
		$this->_Time = substr($item,6,4)."-".substr($item,3,2)."-".substr($item,0,2)." ".substr($item,11,8);
	}

	/**
	 * Parse Text tag
	 *
	 * @access	private
	 * @param	object
	 */
	private function _parseText($item)
	{
		$this->_Text .= $this->_TextPrefix . $item . $this->_TextSuffix;
	}

	/**
	 * Parse Data tag
	 *
	 * @access	private
	 * @param	object
	 */
	private function _parseData($item)
	{
		foreach ($item->children() as $data)
		{
			if ($data->getName() == 'Table')
			{
				$this->_Table='';
				$this->_Table .= "\n<table>\n";

				$this->_parseTable($data);

				$this->_Table .= "</table>\n";
				$this->_Text .= $this->_Table;

			}
		}
	}

	/**
	 * Parse Table tag
	 *
	 * @access	private
	 * @param	object
	 */
	private function _parseTable($table)
	{
		$this->_Table .="<tr>\n";

		foreach ($table->children() as $row)
		{
			if ($row->getName() == 'Column')
			{
				$this->_Table .= "\t<th>".$row."</th>\n";
			}
			if ($row->getName() == 'Row')
			{
				$this->_Table .= "</tr>\n<tr>\n";

				foreach ($row->children() as $cell)
				{
					if ($cell->getName() == 'Cell')
					{
						$this->_Table .= "\t<td>".$cell."</td>\n";
					}
				}
			}
		}

		$this->_Table .="</tr>\n";
	}

	/**
	 * Load XML to object
	 *
	 * @access	private
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	private function _loadXML()
	{
		if ($this->getError()) {return 0;}

		if (!file_exists($this->getXMLDir().$this->getXMLFile()) or !is_file($this->getXMLDir().$this->getXMLFile()))
		{
			$this->_ErrorCollector(__METHOD__,'File ('.$this->getXMLFile().') or directory ('.$this->getXMLDir().') not exist');

			return 0;
		}
			
		$this->_xml = @simplexml_load_file($this->getXMLDir().$this->getXMLFile());

		if (!$this->_xml)
		{
			$this->_ErrorCollector(__METHOD__,'Failed loading XML ('.$this->getXMLDir().$this->getXMLFile().')');

			foreach(libxml_get_errors() as $error)
			{
				$this->_ErrorCollector(__METHOD__,'libxml errors: '.$error->message);
			}
			return 0;
		}
		return 1;
	}

	/**
	 * Set DataBase connect marker on TRUE
	 *
	 * @access	private
	 */
	private function _setDBConnect()
	{
		$this->_dbConnect = true;
	}

	/**
	 * Get DataBase connect marker
	 *
	 * @access	private
	 * @return	boolean	database connection marker
	 */
	private function _getDBConnect()
	{
		return $this->_dbConnect;
	}

	/**
	 * Reset DataBase connect marker
	 *
	 * @access	private
	 */
	private function _resetDBConnect()
	{
		$this->_dbConnect = false;
	}
	/**
	 * Set source directory
	 *
	 * @access	public
	 * @param 	string	XML directory path
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	public function setXMLDir($path)
	{
		if (!file_exists ($path))
		{
			$this->_ErrorCollector(__METHOD__,'Path: '.$path.' not exists');
			return 0;
		}
		$this->_XMLDir = $path;
		return 1;
	}

	/**
	 * Get Source directory
	 *
	 * @access	public
	 * @return	string	XML directory path
	 */
	public function getXMLDir()
	{
		return $this->_XMLDir;
	}

	/**
	 * Set XML filename
	 *
	 * @access	public
	 * @param	string	XML filename
	 * @return	boolean	TRUE on success or FALSE on failure
	 */
	public function setXMLFile($file)
	{
		if (!file_exists ($this->getXMLDir().$file))
		{
			$this->_ErrorCollector(__METHOD__,'File: '.$file.' not exists');
			return 0;
		}
		$this->_XMLFile = $file;
		return 1;
	}

	/**
	 * Get XML filename
	 *
	 * @access	public
	 * @return	string	XML filename
	 */
	public function getXMLFile()
	{
		return $this->_XMLFile;
	}

	/**
	 * Error Collector
	 *
	 * @access	private
	 * @param	string	method
	 * @param	string	error message
	 */
	private function _ErrorCollector($method,$error)
	{
		array_push($this->_errors,array('method'=>$method,'error'=>$error));
		$this->_setError();
	}

	private	function _setError()
	{
		$this->_error = TRUE;
	}

	/**
	 * Check on error
	 *
	 * @access	public
	 * @return	boolean	TRUE if error
	 */
	public function getError()
	{
		return $this->_error;
	}
	/**
	 * Get Errors
	 *
	 * @access	public
	 * @return	array
	 */
	public function getErrors()
	{
		return $this->_errors;
	}
	/**
	 * Destructor
	 */
	public function __destruct()
	{
		if ($this->_getDBConnect())
		{
			$this->dbDisconnect();
		}
		unset($this->_XMLFile);
		unset($this->_XMLDir);
		unset($this->_XMLFileExt);
		unset($this->_errors);
		unset($this->_error);
		unset($this->_xml);
		unset($this->_Title);
		unset($this->_Time);
		unset($this->_Text);
		unset($this->_Table);
		unset($this->_TextPrefix);
		unset($this->_TextSuffix);
		unset($this->_dbLink);
		unset($this->_dbConnect);
	}
}
